#include "AutoCallbackChain.h"

AutoCallbackChain::AutoCallbackChain()
{
    _iEpollFd = epoll_create(256);
}

void AutoCallbackChain::listen()
{
	SocketImpl* p= nullptr;
    while (true){
        epoll_event events[20];
        int nfds = epoll_wait(_iEpollFd, events,  20, -1);  
        for (int i = 0; i < nfds; i++){
			auto iterServer = _mapServerFDs.find(events[i].data.fd);
			if(iterServer != end(_mapServerFDs)){
	    		epoll_event ev;  
        		ev.events = EPOLLIN | EPOLLET;  
        		ev.data.fd = events[i].data.fd;     
        		fcntl(ev.data.fd, F_SETFL, fcntl(ev.data.fd, F_GETFD, 0)|O_NONBLOCK);
        		epoll_ctl(_iEpollFd, EPOLL_CTL_ADD, ev.data.fd, &ev);  
				_mapSocketImpls.insert(pair<int, SocketImpl*>(ev.data.fd, iterServer->second->Accept(ev.data.fd)));	
				continue;
			}else{
            	p = _mapSocketImpls.find(events[i].data.fd)->second;
				if (events[i].events & EPOLLIN){
            	    p->Set_status(SocketStatus::Read);
            	}else if(events[i].events & EPOLLOUT){
                	p->Set_status(SocketStatus::Write);
            	}else{
            	    p->Set_status(SocketStatus::Wait);
               		epoll_ctl(_iEpollFd, EPOLL_CTL_DEL, events[i].data.fd, &events[i]);
					continue;
            	}
            	Task task(p, TaskType::Socket);
        		{
					lock_guard<mutex> lock(_mutex);
            		_mapTasks.insert(pair<int, Task>(events[i].data.fd, task));
				}
			}
        }
    }
}

int AutoCallbackChain::Run()
{
	/*
		1.先循环判断每个TimeChain里面是否有达到时间的对象。
		2.使用select监控所有socket，然后根据相应socket和相应的事件，从map中调用对应的函数	
		3.同步队列和map
		4.每个下需要执行的任务都直接分配给线程池去执行。
	*/
	thread tListen(&AutoCallbackChain::listen, this); tListen.detach();
	while(true){
		lock_guard<mutex> lock(_mutex);
		for(auto ptr = begin(_mapTasks); ptr != end(_mapTasks);){
			switch(ptr->second.Get_type())
			{	
				case TaskType::Socket:{
					int result=1;
					auto p = (SocketImpl*)ptr->second.Get_task();
					while(result){
						switch(p->Get_status())
						{
							case SocketStatus::Read:{
								result = p->Recv();			
								break;
							}
							case SocketStatus::Write:{
								result = p->Send();
								break;
							}
						}
					}
					ptr = _mapTasks.erase(ptr);
					break;
				}
				case TaskType::Time:{
					auto p = (TimeCallbackImpl*)ptr->second.Get_task();
					if(p->IsFinish()){
						p->callback();
						if(!p->ResetStart()){
						    delete p;
						    ptr = _mapTasks.erase(ptr);
						}else{
						    ptr++;
						}
					}
					break;
				}
			}
		}	
	}
}
